﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace Nirvana
{
#if UNITY_EDITOR
    /// <summary>
    /// 角色模型换装，角色模型由多个部位组合而成，暴露的骨骼节点非常多，
    /// 可以通过AnimatorUtility.OptimizeTransformHierarchy接口进行优化。
    /// 意思就是使用该接口将会删除目标对象下的所有transform组件，
    /// 然后animator将写入transform移动矩阵到skin mesh矩阵中以节约大量cpu时间
    /// 2.也可以开启model的Optimize GameoBject选项，一样的功能
    /// </summary>

    public sealed class AnimatorOptimizer : MonoBehaviour
    {
        /// <summary>
        /// 暴露的节点，避免此节点下的特效等子对象在优化时消失
        /// </summary>
        [SerializeField]
        private string[] exposedTransforms;
        /// <summary>
        /// 查找节点的名称，用于曝光查找到的对应的节点
        /// </summary>
        [SerializeField]
        private string[] searchPatterns;
        public string[] ExposedTransforms
        {
            get
            {
                return this.exposedTransforms;
            }
            set
            {
                this.exposedTransforms = value;
            }
        }
        public string[] SearchPatterns
        {
            get
            {
                return this.searchPatterns;
            }
            set
            {
                this.searchPatterns = value;
            }
        }
        /// <summary>
        /// 骨骼优化
        /// </summary>
        public void Optimize()
        {
            AnimatorUtility.OptimizeTransformHierarchy(gameObject, this.ExposedTransforms);
        }
        /// <summary>
        /// 暂时屏蔽骨骼优化
        /// </summary>
        public void Deoptimize()
        {
            AnimatorUtility.DeoptimizeTransformHierarchy(gameObject);
        }

        public void SearchExposed()
        {
            List<string> list = new List<string>();
            foreach(var p in this.searchPatterns)
            {
                if (!string.IsNullOrEmpty(p))
                {
                    Regex regex = new Regex(p);
                    this.MatchRegex(list, transform, regex);
                    list.Clear();
                }
            }
        }

        private void MatchRegex(List<string> list,Transform root,Regex regex)
        {
            list.Add(root.name);
            StringBuilder sb = new StringBuilder();
            for(int i = 0; i < list.Count; i++)
            {
                sb.Append(list[i]);
                if (i < list.Count - 1) sb.Append('/');
            }

            string msg = sb.ToString();
            if (regex.IsMatch(msg))
            {
                MatchSuccess(msg);
            }

            foreach(var p in root)
            {
                var child = (Transform)p;
                this.MatchRegex(list, child, regex);
            }
            list.RemoveAt(list.Count - 1);
        }


        private void MatchSuccess(string txt)
        {
            if(exposedTransforms != null)
            {
                foreach(var p in this.exposedTransforms)
                {
                    if (p == txt) return;
                }
                ArrayUtility.Add<string>(ref this.exposedTransforms, txt);
            }
            else
            {
                this.exposedTransforms = new string[] { txt };
            }
        }
    }
#endif

}

